/*
 * MasterController.java
 *
 * Created on April 17, 2007, 2:59 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package assistedpostagger;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 *
 * @author Paul Arezina
 */
public class MasterController {
    
    HashMap<String, POSDist> vocabPosDist;
    HashMap<String, POSDist> prevTagPosDist;
    HashMap<String, String> validTags;
    POSDist currentWordPosDist;
    TimedReport thisReport;
    private int priorSentences;
    private int futureSentences;
    private int wordCount;
    
    /** Creates a new instance of MasterController */
    public MasterController() throws IOException {
        
        priorSentences = 0;
        futureSentences = 0;
        vocabPosDist = new HashMap();
        prevTagPosDist = new HashMap();
        validTags = new HashMap();
        thisReport = new TimedReport();
        
        String workingDirectory = System.getProperty("user.dir");
        File posTagFile = new File("postags.txt");
        File vocabTagFile = new File("vocabtags.txt");
        File prevTagFile = new File("prevtags.txt");
        File sampleReportFile = new File("samplereport.txt");
        
        BufferedReader bfrPosTags = new BufferedReader(new FileReader(posTagFile));
        BufferedReader bfrVocabTags = new BufferedReader(new FileReader(vocabTagFile));
        BufferedReader bfrPrevTags = new BufferedReader(new FileReader(prevTagFile));
        
        while(bfrPosTags.ready()) {
            String fileLine = bfrPosTags.readLine();
            if (fileLine.contains("\t")) {
                String[] lineSplit = fileLine.split("\\t");
                String pos = lineSplit[0];
                String posDefined = lineSplit[1];
                validTags.put(pos, posDefined);
            }
        }
        
        Pattern wordPattern = Pattern.compile("\\S+");
        
        while(bfrVocabTags.ready()) {
            String fileLine = bfrVocabTags.readLine();
            if(fileLine.contains("/")) {
                POSDist lineDist = new POSDist();
                String[] lineTokens = fileLine.split("\\s+", 2);
                String vocabWord = lineTokens[0];
                Matcher lineMatcher = wordPattern.matcher(lineTokens[1]);
                
                while (lineMatcher.find()) {
                    String posTag = lineMatcher.group();
                    if (posTag.contains("/")) {
                        String[] posTagTokens = posTag.split("/");
                        String pos = posTagTokens[0];
                        Integer posCount = Integer.valueOf(posTagTokens[1]);
                        lineDist.addCount(pos, posCount);
                    }
                }
                vocabPosDist.put(vocabWord, lineDist);
            }                
        }
        
        while(bfrPrevTags.ready()) {
            String fileLine = bfrPrevTags.readLine();
            if(fileLine.contains("/")) {
                POSDist lineDist = new POSDist();
                String[] lineTokens = fileLine.split("\\s+", 2);
                String prevTag = lineTokens[0];
                Matcher lineMatcher = wordPattern.matcher(lineTokens[1]);
                
                while (lineMatcher.find()) {
                    String posTag = lineMatcher.group();
                    if (posTag.contains("/")) {
                        String[] posTagTokens = posTag.split("/");
                        String pos = posTagTokens[0];
                        Integer posCount = Integer.valueOf(posTagTokens[1]);
                        lineDist.addCount(pos, posCount);
                    }
                }
                prevTagPosDist.put(prevTag, lineDist);
            }                
        }
        
        //this.openReport(sampleReportFile);
        
    }
    
    public String getCurrentWord() {
        
        return thisReport.currentWord().getText();
        
    }
    
    public String getCurrentPrevTag() {
        
        return thisReport.currentWord().getPrevPOS();
        
    }
    
    public int getCurrentWordPosition() {
        
        return thisReport.getWordPosition();
        
    }
    
    
    public Vector<String> getSpeechPartList() {
        
        Vector<String> outVector = new Vector();
        
        Iterator<String> keyIterator = validTags.keySet().iterator();
        
        while (keyIterator.hasNext()) {
            
            String pos = keyIterator.next();
            String posDesc = validTags.get(pos);
            outVector.add(pos + " - " + posDesc);
            
        }
        
        Collections.sort(outVector);
        
        return outVector;
        
    }
    
    public ArrayList<String> getValidTags() {
    
        ArrayList<String> outList = new ArrayList(validTags.keySet());
        Collections.sort(outList);
        
        return outList;
        
    }
    
    public void openReport(File reportFile, boolean markUnknowns) throws IOException {
        
        thisReport.open(reportFile, this.getValidTags());
        
        if (!(thisReport.isReportAssisted()) && markUnknowns) {
            this.tagReportUnknown();
        }
        
        thisReport.nextWord();
        
    }
    
    public void saveReport(File reportFile) throws IOException {
        
        thisReport.save(reportFile);
        
    }
    
    public String getSentenceRange() {
        
        int snum = thisReport.getCurrentSentenceNum();
        int stotal = thisReport.getReportSentenceCount();
        
        int prevboundary = snum - this.priorSentences;
        
        if (prevboundary < 0)
            prevboundary = 0;
        
        int futureboundary = snum + this.futureSentences;
        
        if (futureboundary > (stotal - 1))
            futureboundary = stotal - 1;
        
        String reportBlock = "";
        
        for (int i = prevboundary; i < snum; i++) {
            reportBlock = reportBlock.concat(thisReport.getSentence(i));
            reportBlock = reportBlock.concat("  ----  ");
        }
        
        
        reportBlock = reportBlock.concat(thisReport.getPastCurrentSentence());
        reportBlock = reportBlock.concat("__");
        reportBlock = reportBlock.concat(thisReport.currentWord().getText());
        reportBlock = reportBlock.concat("__");
        reportBlock = reportBlock.concat(thisReport.getRemainderCurrentSentence());
       
        for (int i = snum + 1; i <= futureboundary; i++){
            reportBlock = reportBlock.concat("  ----  ");
            reportBlock = reportBlock.concat(thisReport.getSentence(i));            
        }
                
        return reportBlock;
        
    }
    
    public boolean isCurrentWordVocab() {
        
        String word = thisReport.currentWord().getText().toLowerCase();
        
        return this.vocabPosDist.containsKey(word);
        
    }

    public int getPriorSentences() {
        return priorSentences;
    }

    public void setPriorSentences(int priorSentences) {
        this.priorSentences = priorSentences;
    }

    public int getFutureSentences() {
        return futureSentences;
    }

    public void setFutureSentences(int futureSentences) {
        this.futureSentences = futureSentences;
    }

    public int getWordCount() {
        return thisReport.getTotalWords();
    }

    public void updateCurrentWordTag (String newTag) {
        
        thisReport.updateCurrentTag(newTag);
        
    }
    
    public void nextWord() {
        
        thisReport.nextWord();
        
    }
    
    public void previousWord() {
        
        thisReport.previousWord();
        
    }
    
    public void jumpToWord(int index) {
        
        thisReport.setWordIndex(index);
        
    }
    
    public boolean isPreviousWords() {
        
        int currentIndex = this.getCurrentWordPosition();
        
        return (1 != currentIndex);
        
    }
    
    public boolean isNextWords() {
        
        int currentIndex = this.getCurrentWordPosition();
        int lastIndex = this.getWordCount();
        
        return (currentIndex < lastIndex);
        
    }
    
    public String getPrevTag() {
        
        return thisReport.currentWord().getPrevPOS();
        
    }
    
    public ArrayList<POSTuple> buildArrayFromPosDist(POSDist inPos) {
        
        ArrayList<POSTuple> al = new ArrayList();
        
        Iterator<String> keyIT = inPos.getParts().iterator();
        
        while(keyIT.hasNext()) {
            String pos = keyIT.next();
            Integer posPrev = inPos.getPercent(pos);
            al.add(new POSTuple(pos, posPrev));
        }
        
        //List l = al;
        Comparator c = new POSTupleComparator();
        Collections.sort(al, c);
        
        return al;
        
    }
    
    public ArrayList<POSTuple> getVocabTagDist() {
        
        if (!(this.isCurrentWordVocab()))
            return null;
        
        String vocabWord = thisReport.currentWord().getText().toLowerCase();
        POSDist vocabPos = this.vocabPosDist.get(vocabWord);
        
        return buildArrayFromPosDist(vocabPos);
                
    }
    
    public ArrayList<POSTuple> getPrevTagDist() {
        
        String prevTag = thisReport.currentWord().getPrevPOS();
        POSDist prevPOS = this.prevTagPosDist.get(prevTag);
        
        return buildArrayFromPosDist(prevPOS);
            
        
    }

    public String getWordTag() {
        
        return thisReport.getWordTag();
        
    }
    
    public ArrayList<POSTuple> getBigramPosDist() {
        
        if (!(this.isCurrentWordVocab()))
            return null;
        
        String vocabWord = thisReport.currentWord().getText().toLowerCase();
        POSDist vocabPos = this.vocabPosDist.get(vocabWord);
        String prevTag = thisReport.currentWord().getPrevPOS();
        POSDist prevPOS = this.prevTagPosDist.get(prevTag);
        
        POSDist bigramPOS = new POSDist();
        
        Iterator<String> keyIT = vocabPos.getParts().iterator();
        
        while (keyIT.hasNext()) {
                        
            String pos = keyIT.next();
            if (prevTagPosDist.containsKey(pos)) {
                
                Integer vocabPercent = vocabPos.getPercent(pos);
                Integer prevTagPercent = prevPOS.getPercent(pos);
                bigramPOS.addCount(pos, vocabPercent * prevTagPercent);
                
            }            
                        
        }
        
        return buildArrayFromPosDist(bigramPOS);
        
    }
    
    public boolean isReportAssisted() {
        
        return this.thisReport.isReportAssisted();
        
    }
    
    public void tagReportUnknown() {
        
        thisReport.tagReportUnknown(this.getValidTags());
        
    }
    
    public boolean isAnyReportUnknowns() {
        
        boolean isUnknown = thisReport.isAnyReportUnknowns();
        
        return isUnknown;
        
    }
    
    
}
